/*================================================================
*   Copyright (C) 2020 Sangfor Ltd. All rights reserved.
*   
*   文件名称：SelectSvr.hpp
*   创 建 者：Ann
*   创建日期：2020年05月17日
*   描    述：
*
================================================================*/

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <vector>

#include "tcpsvr.hpp"

class SelectSvr
{
    public:
        SelectSvr()
        {
            FD_ZERO(&readfds_);
            max_readfd_= -1;
        }
        //添加
        void Add(int fd)
        {
            //添加到集合当中
            FD_SET(fd, &readfds_);
            //更新一下最大的文件描述符
            if(fd > max_readfd_)
            {
                max_readfd_ = fd;
            }
        }
        //删除
        void DeleteFd(int fd)
        {
            //删除
            FD_CLR(fd, &readfds_);
            //更新
            for(int i = max_readfd_; i >= 0; i--)
            {
                if(!FD_ISSET(i, &readfds_))
                {
                    continue;
                }
                max_readfd_ = i;
                break;
            }
        }
        //监控
        //bool SelectWait(std::vector<int>* vec, int usec = 100)
        bool SelectWait(std::vector<TcpServer>* vec, int usec = 100)
        {
            struct timeval tv;
            tv.tv_sec = 0;
            tv.tv_usec = usec;

            //监控
            fd_set tmp = readfds_;
            int ret = select(max_readfd_ + 1, &tmp, NULL, NULL, &tv);
            if(ret < 0)
            {
                perror("select");
                return false;
            }
            else if(ret == 0)
            {
                //printf("select timeout\n");
                return false;
            }

            //select 返回ret大于0的情况
            for(int i = 0; i <= max_readfd_; i++)
            {
                if(FD_ISSET(i, &tmp))
                {
                    TcpServer ts;
                    ts.SetFd(i); 
                    vec->push_back(ts);
                }
            }
           return true;
        }
    private:
        fd_set readfds_;
        //当前想让select监听的最大的文件描述符，为了给select传递nfds的时候使用
        int max_readfd_;
};
